import time
import threading

class IdWorker:
    EPOCH = 1288834974657  # Twitter Snowflake 的默认纪元时间：2010-11-04 UTC

    NODE_BITS = 10
    SEQUENCE_BITS = 12

    MAX_NODE_ID = ~(-1 << NODE_BITS)  # 最大 node_id (2^10 - 1 = 1023)
    MAX_SEQUENCE = ~(-1 << SEQUENCE_BITS)  # 最大 sequence (2^12 - 1 = 4095)

    _instance = None  # 单例模式
    _lock = threading.Lock()  # 线程锁

    def __init__(self, node_id=1):
        if node_id > self.MAX_NODE_ID or node_id < 0:
            raise ValueError(f"node_id must be between 0 and {self.MAX_NODE_ID}")

        self.node_id = node_id
        self.last_timestamp = -1
        self.sequence = 0

        self.NODE_SHIFT = self.SEQUENCE_BITS
        self.TIMESTAMP_SHIFT = self.NODE_BITS + self.SEQUENCE_BITS

    def _gen_timestamp(self):
        return int(time.time() * 1000) - self.EPOCH

    def _til_next_millis(self, last_timestamp):
        timestamp = self._gen_timestamp()
        while timestamp <= last_timestamp:
            timestamp = self._gen_timestamp()
        return timestamp

    def next_id(self):
        with self._lock:  # 确保线程安全
            timestamp = self._gen_timestamp()

            if timestamp < self.last_timestamp:
                raise Exception("时钟回拨")

            if timestamp == self.last_timestamp:
                self.sequence = (self.sequence + 1) & self.MAX_SEQUENCE
                if self.sequence == 0:
                    timestamp = self._til_next_millis(self.last_timestamp)
            else:
                self.sequence = 0

            self.last_timestamp = timestamp

            new_id = ((timestamp << self.TIMESTAMP_SHIFT)
                      | (self.node_id << self.SEQUENCE_BITS)
                      | self.sequence)

            return new_id

    @classmethod
    def GetIdStr(cls):
        """静态方法，无需传入参数即可获取雪花ID"""
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = cls(node_id=1)  # 固定使用 node_id=1
        return cls._instance.next_id()
